#pragma once

#include <vector>
#include "downsample.h"

namespace img {

enum copy_original_t { copy_original };
enum not_copy_original_t { not_copy_original };

template <typename R>
struct pyramid {
	/// downsampled[0] points on the provided image (may copy or just point on it)
	/// downsampled[1]...downsampled[levels] contain diminishing copies of original image
	std::vector<R> downsampled;
public:
	pyramid() { }
	pyramid(R const & r, size_t levels, not_copy_original_t) 
		{ reset(r, levels, not_copy_original); }
	pyramid(R const & r, size_t levels, copy_original_t)
		{ reset(r, levels, copy_original); }
	void reset(R const & r, size_t levels, not_copy_original_t) {
		downsampled.resize(levels+1);
		downsampled[0].attach(r);
		build(0, levels);
	}
	void reset(R const & r, size_t levels, copy_original_t) {
		downsampled.resize(levels+1);
		downsampled[0] = r;
		build(0, levels);
	}
	void resize(size_t levels) {
		size_t were_levels = levels_count();
		if (were_levels == levels)
			return;
		downsampled.resize(levels + 1);
		if (were_levels < levels) {
			downsampled.resize(levels + 1);
			build(were_levels, levels);
		}
	}
	size_t levels_count() const {
		assert (downsampled.size() > 0);
		return downsampled.size() - 1; 
	}
	R const & operator [] (size_t l) const
		{ return downsampled[l]; }
	R & operator [] (size_t l)
		{ return downsampled[l]; }
private:
	void build(size_t base, size_t levels) {
		for (size_t l = base + 1; l <= levels; ++l)
			img::downsample(downsampled[l-1], downsampled[l], 2);
	}
};


} //namespace img
